//
//  NSDate+RCExpand.m
//  NSDate

//iOS-NSDateFormatter 格式说明：
//
//G: 公元时代，例如AD公元
//yy: 年的后2位
//yyyy: 完整年
//MM: 月，显示为1-12
//MMM: 月，显示为英文月份简写,如 Jan
//MMMM: 月，显示为英文月份全称，如 Janualy
//dd: 日，2位数表示，如02
//d: 日，1-2位显示，如 2
//EEE: 简写星期几，如Sun
//EEEE: 全写星期几，如Sunday
//aa: 上下午，AM/PM
//H: 时，24小时制，0-23
//K：时，12小时制，0-11
//m: 分，1-2位
//mm: 分，2位
//s: 秒，1-2位
//ss: 秒，2位
//S: 毫秒
//
//  Created by 杨晓辉 on 2017/7/19.
//  Copyright © 2017年 杨晓辉. All rights reserved.
//

#import "NSDate+RCExpand.h"
static const unsigned componentFlags = (NSCalendarUnitYear| NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour |  NSCalendarUnitMinute | NSCalendarUnitSecond |NSCalendarUnitWeekOfMonth| NSCalendarUnitWeekOfYear|NSCalendarUnitWeekday | NSCalendarUnitWeekdayOrdinal);

static NSString *defaultFormatter = @"yyyy-MM-dd";



static NSString *kFormatMonthFullDateWithTime    = @"MMM dd yyyy h:mm a";
static NSString *kFormatYearFullDateWithTime    = @"yyyy dd MMM h:mm a";
static NSString *kFormatWeekWithTime = @"EEEE HH:mm:ss";
static NSString *kFormatWeek =@"EEEE";
static NSString *kFormatShortWeek =@"EEE";
static NSString *kFormatTime = @"HH:mm:ss";

static NSString *kFormatDashYearFullDate = @"yyyy-MM-dd HH:mm:ss";
static NSString *kFormatDashYearDate = @"yyyy-MM-dd";
static NSString *kFormatDashMonthFullDate = @"MM-yyyy-dd HH:mm:ss";
static NSString *kFormatDashMonthDate = @"MM-yyyy-dd";

static NSString *kFormatSpaceYearFullDate = @"yyyy MM dd HH:mm:ss";
static NSString *kFormatSpaceYearDate = @"yyyy MM dd";
static NSString *kFormatSpaceMonthFullDate = @"MM yyyy dd HH:mm:ss";
static NSString *kFormatSpaceMonthDate = @"MM yyyy dd";

static NSString *kFormatSolidusYearFullDate = @"yyyy/MM/dd HH:mm:ss";
static NSString *kFormatSolidusYearDate = @"yyyy/MM/dd";
static NSString *kFormatSolidusMonthFullDate = @"MM/yyyy/dd HH:mm:ss";
static NSString *kFormatSolidusMonthDate = @"MM/yyyy/dd";

static NSString *kFormatYearFullDate = @"yyyyMMddHHmmss";
static NSString *kFormatYearDate = @"yyyyMMdd";
static NSString *kFormatMonthFullDate = @"MMyyyyddHHmmss";
static NSString *kFormatMonthDate = @"MMyyyydd";

@implementation NSDate (RCExpand)

/**
 获取当前日历
 
 @return 返回一个单利对象
 */
+ (NSCalendar *) currentCalendar
{
    static dispatch_once_t onceToken;
    static NSCalendar *sharedCalender = nil;
    
    dispatch_once(&onceToken, ^{
        if (sharedCalender==nil) {
            sharedCalender = [NSCalendar autoupdatingCurrentCalendar];
        }
    });
    return sharedCalender;
}
/**
 
 获取相邻几天的日期
 @param dayNum 天数
 @param format 传入的日期格式
 @param date 传入的日期
 @return 返回结果
 */
+ (NSString *)getDateSinceDay:(NSInteger)dayNum format:(NSString *)format date:(NSDate*)date
{
    
    if (format==nil) {
        format=defaultFormatter;
    }
    if (date==nil) {
        date=[NSDate date];
    }
    NSDateFormatter *formatter=[[NSDateFormatter alloc]init];
    [formatter setDateFormat:format];
    if (dayNum) {
        NSDate *newDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate:([date timeIntervalSinceReferenceDate] + dayNum*24*3600)];
        date=newDate;
    }
    NSString *returnstr=[formatter stringFromDate:date];
    return returnstr;
    
}

/**
 获取手机语言时区的时间
 
 @param date 传入的日期
 @return 返回的日期结果
 */
+ (NSDate*)getLocalDate:(NSDate*)date
{
    
    NSTimeZone *zone = [NSTimeZone systemTimeZone];
    
    NSInteger interval = [zone secondsFromGMTForDate: date];
    
    NSDate *localeDate = [date  dateByAddingTimeInterval: interval];
    return localeDate;
}

/**
 NSstring 转换为Date
 
 @param dateString 传入的日期字符串
 @param format 传入的日期格式
 @return 返回结果
 */
+ (NSDate *)dateFromString:(NSString *)dateString format:(NSString*)format
{
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:format];
    dateFormat.locale = [NSLocale currentLocale];
    dateFormat.timeZone = [NSTimeZone localTimeZone];
    NSDate *date = [dateFormat dateFromString:dateString];
    return date;
}
/**
 Date转换为 NSstring
 
 @param date 传入的日期
 @param format 传入的日期格式
 @return 返回结果
 */
+ (NSString*)stringFromDate:(NSDate*)date withFormString:(NSString*)format
{
    
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:format];
    NSString *srting = [dateFormat stringFromDate:date];
    return srting;
}

/**
 Date转换为 NSstring
 
 @param date 传入的日期
 @param dateStyle 时间样式
 @return 返回结果
 */
+ (NSString *)dateFromStringWithDateStyle:(NSDateFormatterStyle)dateStyle date:(NSDate*)date
{
    
    NSDateFormatter* fmt = [[NSDateFormatter alloc] init];
    fmt.dateStyle = kCFISO8601DateFormatWithWeekOfYear |kCFISO8601DateFormatWithFullDate;
    fmt.timeStyle = kCFISO8601DateFormatWithWeekOfYear;
    NSLocale *locale = [NSLocale currentLocale];
    fmt.locale = locale;
    NSString* dateString = [fmt stringFromDate:date];
    return dateString;
}

/**
 获取时间字符串，毫秒数
 
 @return 返回毫秒数
 */
+ (NSString *)dateTimeString
{
    UInt64 recordTime = [[NSDate date] timeIntervalSince1970]*1000;
    NSString *time = [[NSString alloc] initWithFormat:@"%llu", recordTime];
    return time;
}

/**
 根据日期得到星期

 @param inputDate 传入的日期
 @return 返回的星期
 */
+ (NSString*)weekdayStringFromDate:(NSDate*)inputDate
{
    
    NSArray *weekdays = [NSArray arrayWithObjects: [NSNull null],@"星期日", @"星期一", @"星期二", @"星期三", @"星期四", @"星期五", @"星期六", nil];
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    NSTimeZone *timeZone = [NSTimeZone systemTimeZone] ;
    [calendar setTimeZone: timeZone];
    NSCalendarUnit calendarUnit = NSCalendarUnitWeekday;
    NSDateComponents *theComponents = [calendar components:calendarUnit fromDate:inputDate];
    return [weekdays objectAtIndex:theComponents.weekday];
}
#pragma mark ---@property--



/**
 取得日期的年数
 
 @return 返回得到年数
 */
- (NSInteger) dateYearField
{
    NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
    return components.year;
}

/**
 取得日期的月数
 
 @return 返回得到月数
 */
- (NSInteger) dateMonthField
{
    NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
    return components.month;
}
/**
 取得日期的天数
 
 @return 返回得到天数
 */
- (NSInteger) dateDayField
{
    NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
    return components.day;
}

/**
 取日期的小时(hour)字段
 
 @return 返回得到的小时数
 */
- (NSInteger) dateHourField
{
    NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
    return components.hour;

}

///从时间中分离出小时和分钟等时间元素
- (NSDateComponents *)getDateComponentsFromCurrentDate{
    
    NSDate *now = [NSDate date];
//    NSLog(@"now date is: %@", now);
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSUInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    NSDateComponents *dateComponent = [calendar components:unitFlags fromDate:now];
    
    return dateComponent;
}

/**
 取得日期的分钟数
 
 @return 返回分钟数
 */
- (NSInteger) dateMinuteField
{
    NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
    
    return components.minute;
    
}

/**
 取得日期的秒数
 
 @return 返回得到秒数
 */
- (NSInteger) dateSecondsField
{
    NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
    return components.second;
}
/**
 取得日期当前年份的第几周
 
 @return 返回得到第几周
 */
- (NSInteger) weekOfYear
{
    NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
    return components.weekOfYear;
}
/**
 取得日期当前月份的第几周
 
 @return 返回得到第几周
 */
- (NSInteger) weekOfMonth
{
    NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
    return components.weekOfMonth;
}

/**
 星期序号

 @return 返回星期序号
 */
- (NSInteger) weekday
{
    
    NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
    return components.weekday;
}


/**
 设置日的格式

 @param dateFormatter 日期格式
 @return 返回设置后的值
 */
- (NSString *)setDateFormatter:(NSString *)dateFormatter
{
        NSDateFormatter * fmt= [[NSDateFormatter alloc] init];
        fmt.dateFormat = dateFormatter;
     return  [fmt stringFromDate:self];
}

- (NSString *) defaultFormatter
{
    return defaultFormatter;
}


- (NSString *) formatterSolidusYMD
{
    return @"yyyy/MM/dd";
}
- (NSString *) formatterWhippletreeYMD
{
    return @"yyyy-MM-dd";
}

- (NSString *) formatterSpaceYMD
{
    return @"yyyy MM dd";
}

- (NSString *) formatterYMD
{
    return @"yyyyMMdd";
}
- (NSString *) formatterSolidusFull
{
    return @"yyyy/MM/dd HH:mm:ss";
}

- (NSString *) formatterWhippletreeFull
{
    return @"yyyy-MM-dd HH:mm:ss";
}

- (NSString *) formatterSpaceFull
{
    return @"yyyy MM dd HH:mm:ss";
}

- (NSString *) formatterFull
{
    return @"yyyyMMddHHmmss";
}


- (NSString *) formatterSolidusMDY
{
    return @"MM/dd/yyyy";
}

- (NSString *) formatterWhippletreeMDY
{
    return @"MM-dd-yyyy";
}

- (NSString *) formatterSpaceMDY
{
    return @"MM dd yyyy";
}

- (NSString *) formatterMDY
{
    return @"MMddyyyy";
}

- (NSString *) formatterSolidusMDYFull
{
    return @"MM/dd/yyyy HH:mm:ss";
}

- (NSString *) formatterWhippletreeMDYFull
{
    return @"MM-dd-yyyy HH:mm:ss";
}

- (NSString *) formatterSpaceMDYFull
{
    return @"MM dd yyyy HH:mm:ss";
}

- (NSString *) formatterMDYFull
{
    return @"MMddyyyyHHmmss";
}




- (NSUInteger)daysInYear {
    return [NSDate daysInYear:self];
}

+ (NSUInteger)daysInYear:(NSDate *)date {
    return [self isLeapYear:date] ? 366 : 365;
}



- (BOOL)isLeapYear {
    return [NSDate isLeapYear:self];
}

+ (BOOL)isLeapYear:(NSDate *)date {
    NSUInteger year = [date dateYearField];
    if ((year % 4  == 0 && year % 100 != 0) || year % 400 == 0) {
        return YES;
    }
    return NO;
}

/**
 * 返回x分钟前/x小时前/昨天/x天前/x个月前/x年前
 */
- (NSString *)timeInfo {
    return [NSDate timeInfoWithDate:self];
}

+ (NSString *)timeInfoWithDate:(NSDate *)date {
    return [self timeInfoWithDateString:[self stringFromDate:date withFormString: kFormatDashYearFullDate]];
}

+ (NSString *)timeInfoWithDateString:(NSString *)dateString {
    NSDate *date = [self dateFromString:dateString format:kFormatDashYearFullDate];
    
    NSDate *curDate = [NSDate date];
    NSTimeInterval time = [date timeIntervalSinceDate:curDate];
    
    int month = (int)([curDate dateMonthField] - [date dateMonthField]);
    int year = (int)([curDate dateYearField] - [date dateYearField]);
    int day = (int)([curDate dateDayField] - [date dateDayField]);
    
    NSTimeInterval retTime = 1.0;
    if (time < 3600) { // 小于一小时
        retTime = time / 60;
        retTime = retTime <= 0.0 ? 1.0 : retTime;
        return [NSString stringWithFormat:@"%.0f分钟前", retTime];
    } else if (time < 3600 * 24) { // 小于一天，也就是今天
        retTime = time / 3600;
        retTime = retTime <= 0.0 ? 1.0 : retTime;
        return [NSString stringWithFormat:@"%.0f小时前", retTime];
    } else if (time < 3600 * 24 * 2) {
        return @"昨天";
    }
    // 第一个条件是同年，且相隔时间在一个月内
    // 第二个条件是隔年，对于隔年，只能是去年12月与今年1月这种情况
    else if ((abs(year) == 0 && abs(month) <= 1)
             || (abs(year) == 1 && [curDate dateMonthField] == 1 && [date dateMonthField] == 12)) {
        int retDay = 0;
        if (year == 0) { // 同年
            if (month == 0) { // 同月
                retDay = day;
            }
        }
        
        if (retDay <= 0) {
            // 获取发布日期中，该月有多少天
            int totalDays = (int)[self daysInMonth:date month:[date dateMonthField]];
            
            // 当前天数 + （发布日期月中的总天数-发布日期月中发布日，即等于距离今天的天数）
            retDay = (int)[curDate dateDayField] + (totalDays - (int)[date dateDayField]);
        }
        
        return [NSString stringWithFormat:@"%d天前", (abs)(retDay)];
    } else  {
        if (abs(year) <= 1) {
            if (year == 0) { // 同年
                return [NSString stringWithFormat:@"%d个月前", abs(month)];
            }
            
            // 隔年
            int month = (int)[curDate dateMonthField];
            int preMonth = (int)[date dateMonthField];
            if (month == 12 && preMonth == 12) {// 隔年，但同月，就作为满一年来计算
                return @"1年前";
            }
            return [NSString stringWithFormat:@"%d个月前", (abs)(12 - preMonth + month)];
        }
        
        return [NSString stringWithFormat:@"%d年前", abs(year)];
    }
    
    return @"1小时前";
}



- (NSUInteger)daysInMonth:(NSUInteger)month {
    return [NSDate daysInMonth:self month:month];
}

+ (NSUInteger)daysInMonth:(NSDate *)date month:(NSUInteger)month {
    switch (month) {
        case 1: case 3: case 5: case 7: case 8: case 10: case 12:
            return 31;
        case 2:
            return [date isLeapYear] ? 29 : 28;
    }
    return 30;
}

- (NSDate *)offsetYears:(int)numYears {
    return [NSDate offsetYears:numYears fromDate:self];
}

+ (NSDate *)offsetYears:(int)numYears fromDate:(NSDate *)fromDate {
    if (fromDate == nil) {
        return nil;
    }

    NSCalendar *gregorian = [[NSCalendar alloc]
                             initWithCalendarIdentifier:NSCalendarIdentifierGregorian];

    
    NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
    [offsetComponents setYear:numYears];
    
    return [gregorian dateByAddingComponents:offsetComponents
                                      toDate:fromDate
                                     options:0];
}

- (NSDate *)offsetMonths:(int)numMonths {
    return [NSDate offsetMonths:numMonths fromDate:self];
}

+ (NSDate *)offsetMonths:(int)numMonths fromDate:(NSDate *)fromDate {
    if (fromDate == nil) {
        return nil;
    }

    NSCalendar *gregorian = [[NSCalendar alloc]
                             initWithCalendarIdentifier:NSCalendarIdentifierGregorian];

    
    NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
    [offsetComponents setMonth:numMonths];
    
    return [gregorian dateByAddingComponents:offsetComponents
                                      toDate:fromDate
                                     options:0];
}

- (NSDate *)offsetDays:(int)numDays {
    return [NSDate offsetDays:numDays fromDate:self];
}

+ (NSDate *)offsetDays:(int)numDays fromDate:(NSDate *)fromDate {
    if (fromDate == nil) {
        return nil;
    }
    
    NSCalendar *gregorian = [[NSCalendar alloc]
                             initWithCalendarIdentifier:NSCalendarIdentifierGregorian];

    
    
    NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
    [offsetComponents setDay:numDays];
    
    return [gregorian dateByAddingComponents:offsetComponents
                                      toDate:fromDate
                                     options:0];
}

- (NSDate *)offsetHours:(int)hours {
    return [NSDate offsetHours:hours fromDate:self];
}

+ (NSDate *)offsetHours:(int)numHours fromDate:(NSDate *)fromDate {
    if (fromDate == nil) {
        return nil;
    }
    

    NSCalendar *gregorian = [[NSCalendar alloc]
                             initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    
    
    NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
    [offsetComponents setHour:numHours];
    
    return [gregorian dateByAddingComponents:offsetComponents
                                      toDate:fromDate
                                     options:0];
}

@end
